<?php

    /**
     * @package      Modules
     * @subpackage   Base_Controllers_Admin
     *
     * @license      GNU Lesser General Public Licence see LICENCE-LGPL file or http://www.gnu.org/licenses/lgpl.html
     */
    abstract class Base_Controllers_Admin_Index extends Core_Controller_Action_Abstract
    {

    ////////////////////////////////////////////////////////////////////////////
    //                                Variables                               //
    ////////////////////////////////////////////////////////////////////////////

       /**
        * Parameters for plugin
        *
        * @var array
        */
        protected $_pluginParams = array('*' => array('auth.required' => true, 'acl.required' => true));

        /**
         * Default namespace
         *
         * @var Zend_Session_Namespace
         */
        protected $_namespace = null;

        /**
         * Files upload options.
         *
         * @var array
         */
		protected $_files	= array();

        /**
         * Model class
         *
         * @var string
         */
        protected $_model           = null;

        /**
         * Optional model class
         *
         * @var string
         */
        protected $_parent          = null;

        /**
         * Optional adjacent class (in the same list, model's son)
         * 
         * @var     string
         */
        protected $_adjacent  = null;

        /**
         * Search fields
         *
         * @var array
         */
        protected $_search          = array();

        /**
         * List parameters
         *
         * @var array
         */
        protected $_listParam       = array();

        /**
         * Array of elements in cache
         *
         * @var array
         */
        protected $_cache           = array();

	////////////////////////////////////////////////////////////////////////////
	//                            Constants                                   //
	////////////////////////////////////////////////////////////////////////////

        const LIST_TYPE_ADJACENCY   = 'adjacency';

	////////////////////////////////////////////////////////////////////////////
	//                          Public Methods                                //
	////////////////////////////////////////////////////////////////////////////

        /**
         * Constructor
         *
         * @param       Core_Controller_Request_Abstract     $request
         */
        public function __construct(Core_Controller_Request_Abstract $request)
        {
            parent::__construct($request);

            $this->_namespace			= new Zend_Session_Namespace('Default');
            $this->_namespace->errors	= array();
        }

        /**
         * Generic action to load a list
         *
         * @param       string      $method
         * @return      Core_Controller_Response_Abstract
         */
        private function _list($function)
        {
            $rep            = $this->_getResponse('json');

            $model          = $this->_model;
            $parent         = $this->_parent;

            if ($this->_getParam('listType') == self::LIST_TYPE_ADJACENCY) {
                if ($this->_getParam('anode') === null) {
                    $model      = $this->_adjacent;
                } else {
                    $anode      = explode('-', $this->_getParam('anode'));
                    $this->_setParam('rel-'. $this->_adjacent, '=__'. $anode[1]);
                }
            }

            $queries        = $this->_getQueries($function, $model, $parent);
            $elements       = $this->_getElements($queries, $model, $parent);
            $totalElements  = $this->_getTotalCount();

            $rep->setResponseCount($totalElements);
            $rep->setResponseContent(toHtmlEntities($elements));
            return $rep;
        }

        /**
         * Default action: list all the elements
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function index()
        {
            return $this->_list(__FUNCTION__);
        }

        /**
         * List of elements in the trash
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function trash()
        {
            return $this->_list(__FUNCTION__);
        }

        /**
         * Return searched fields and values
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function search()
        {
            $params         = $this->_getParams();
            $cleanParams    = array();

            $_modelTable    = Doctrine::getTable($this->_model);
            
            if (!empty($this->_parent)) {
                $_parentTable   = Doctrine::getTable($this->_parent);
            }

            foreach ($params as $paramKey => $paramValue) {
                $exploded   = explode('-', $paramKey);

                if ($exploded[0] == 'rel') {
                    // Field is a relation

                    if ($_modelTable->hasRelation($exploded[1])) {
                        $cleanParams[$paramKey] = $paramValue;
                    }

                    if (!empty($this->_parent) && ($_parentTable->hasField($exploded[1]))) {
                        $cleanParams[$paramKey] = $paramValue;
                    }
                } else {
                    // Field is a simple field
                    if ($_modelTable->hasField($paramKey)) {
                        $cleanParams[$paramKey] = $paramValue;
                    }

                    if (!empty($this->_parent) && ($_parentTable->hasField($paramKey))) {
                        $cleanParams[$paramKey] = $paramValue;
                    }
                }
            }

            $rep = $this->_getResponse('http');
            $rep->setTemplate('json.tpl');
            $rep->data->assign('json', Zend_Json::encode(array( 'success'   => true,
                                                                'errors'    => array(),
                                                                'params'    => $cleanParams
                                                              )));
            return $rep;
        }

        /**
         * Loads the advanced search form
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function advancedSearch()
        {
            return $this->_form(__FUNCTION__, $this->_model);
        }

        /**
         * Loads the edition form
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function edit()
        {
            return $this->_form(__FUNCTION__, $this->_model);
        }

        /**
         * Loads the edit parent form
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function editParent()
        {
            return $this->_form(__FUNCTION__, $this->_parent);
        }

        /**
         * Loads the add form
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function add()
        {
            return $this->_form(__FUNCTION__, $this->_model);
        }

        /**
         * Loads the add parent form
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function addParent()
        {
            return $this->_form(__FUNCTION__, $this->_parent);
        }

        /**
         * Saves the modifications
         *
         * @throws      Core_Exception
         * @return      Core_Controller_Response_Abstract
         */
        public function save()
        {
            $item                           = null;
            $customs = $files = $manyToMany = array();
            $items                          = array();
            $action                         = $this->_getParam('_prevAction');
            $model                          = $this->_getParam('_model');
            $language                       = $this->_getParam('_language');

            if ($this->_getParam('todoaction') == 'edit' && ($this->_intParam('id') !== null) || ($this->_getParam('idList') !== null)) {
                // Multiple edition
                if ($this->_getParam('idList') !== null) {
                    $items = Doctrine_Query::create()->from($model)->whereIn('id', explode('-', $this->_getParam('idList')))->execute();
                }

                // Single edition
                if ($this->_intParam('id') !== null) {
                    $items[] = Doctrine_Query::create()->from($model)->where('id = ?', $this->_intParam('id'))->fetchOne();
                }

                if (count($items) == 0) {
                    throw new Core_Exception('Element must exists to be edited');
                }

            } else {
                // New item
                $item			= new $model();
                $item->status	= DbBase::ENABLED;
                $items[]        = $item;
            }

            foreach ($items as $item) {
                if ($item instanceof DbBase) {
                    $columns = $item->getTable()->getColumns();

                    try {
                        foreach ($this->_getParams() as $paramKey => $paramValue) {
                            // Explodes the key to retrieve special attributes
                            $_rel     = explode('rel-',         $paramKey);
                            $_i18n    = explode('i18n-',        $paramKey);
                            $_date    = explode('date-',        $paramKey);
                            $_datetime= explode('timestamp-',   $paramKey);
                            $_time    = explode('time-',        $paramKey);
                            $_cust    = explode('custom-',      $paramKey);
                            $_file    = explode('file-',        $paramKey);

                            if (isset($_cust[1])) {
                                // Custom field
                                $cust = explode('-', $_cust[1]);

                                if (!isset($customs[$cust[0]])) {
                                    $customs[$cust[0]]['object']  = new $cust[0]();
                                    $customs[$cust[0]]['valid']   = true;
                                }

                                try {
                                    $customs[$cust[0]]['object']->validate($item, $cust[1], $paramValue);

                                } catch (Base_Classes_Customs_Exception $e) {
                                    // Sets the custom invalid
                                    $customs[$cust[0]]['valid'] = false;

                                    foreach ($e->getErrors() as $fieldName => $errorCodes) {
                                        foreach ($errorCodes as $value) {
                                            $this->_namespace->errors[$fieldName][] = $value;
                                        }
                                    }
                                }

                            } else if (isset($_rel[1])) {
                                // Relation field
                                $_manyToMany = explode('-', $_rel[1]);

                                if (isset($_manyToMany[1])) {
                                    if ($paramValue == 'on') {
                                        $manyToMany[$_manyToMany[0]][] = $_manyToMany[1];
                                    }
                                    continue;
                                }

                                $_modelClass  = $this->_model;
                                $_modelTable  = Doctrine::getTable($_modelClass);

                                if ($_rel[1] == $this->_parent) {
                                    // Relation to a parent class
                                    $parentClass = (get_class($item) == $this->_parent) ? $this->_parent : $item->getTable()->getRelation($this->_parent)->getClass();
                                    $parentTable = Doctrine::getTable($parentClass);

                                    // Parent to parent relation
                                    if (empty($paramValue)) {
                                        // No parent
                                        switch (get_class($item)) {
                                            case $parentClass:
                                                // Gets the root element
                                                $rootElement = $this->_getRootElement($parentClass);

                                                // We save the root element in wich we insert the current item
                                                if ($item->exists()) {
                                                    $_moveInNode    = $rootElement;
                                                } else {
                                                    $_insertInNode  = $rootElement;
                                                }
                                                break;

                                            case $this->_model:
                                                $item->$_rel[1] = null;
                                                break;
                                        }

                                    } else {
                                        // A parent is set
                                        switch (get_class($item)) {
                                            case $parentClass:
                                                // Gets the root element
                                                $rootElement = $this->_getRootElement($this->_parent, $paramValue);

                                                // We save the root element in wich we insert the current item
                                                if ($item->exists()) {
                                                    $_moveInNode    = $rootElement;
                                                } else {
                                                    $_insertInNode  = $rootElement;
                                                }
                                                break;

                                            case $this->_model:
                                                $item->$_rel[1] = $parentTable->find($paramValue);
                                                break;
                                        }
                                    }

                                } elseif ($_rel[1] == $this->_model) {
                                    // Relation with the same model, it's a nested set

                                    if (empty($paramValue)) {
                                        // There is no parent
                                        // Gets the root element
                                        $_rootElement = Doctrine_Query::create()
                                                            ->from($_modelClass)
                                                            ->where('level = ?', 0)
                                                            ->fetchOne();

                                        // Creation of the root element for the parent if not exists
                                        if (!$_rootElement) {
                                            $_rootElement                 = new $_modelClass();
                                            $_rootElement->status         = DbBase::ROOT;

                                            // If the element has a slug
                                            if ($_modelTable->hasTemplate('Doctrine_Template_Sluggable')) {
                                                $_rootElement->slug = 'root';
                                            }

                                            $_rootElement->save();
                                            $_modelTable->getTree()->createRoot($_rootElement);
                                        }

                                        // We save the root element in wich we insert the current item
                                        if ($item->exists()) {
                                            $_moveInNode    = $_rootElement;
                                        } else {
                                            $_insertInNode  = $_rootElement;
                                        }
                                    } else {
                                        // There is a parent
                                        // Gets the root element
                                        $_rootElementOfParent = Doctrine_Query::create()->from($_modelClass)
                                                                                        ->where('id = ?', $paramValue)
                                                                                        ->fetchOne();

                                        // Creation of the root element if not exists
                                        if (!$_rootElementOfParent) {
                                            $_rootElementOfParent                 = new $_modelClass();
                                            $_rootElementOfParent->status         = DbBase::ROOT;

                                            // If the element has a slug
                                            if ($_modelTable->hasTemplate('Doctrine_Template_Sluggable')) {
                                                $_rootElementOfParent->slug = 'root';
                                            }

                                            $_modelTable->getTree()->createRoot($_rootElementOfParent);
                                        }

                                        // We save the root element in wich we insert the current item
                                        if ($item->exists()) {
                                            $_moveInNode    = $_rootElementOfParent;
                                        } else {
                                            $_insertInNode  = $_rootElementOfParent;
                                        }
                                    }

                                } else if ($item->hasRelation($_rel[1])) {
                                    // Relation with another class than the parent class
                                    $_relation = $item->getTable()->getRelation($_rel[1]);

                                    if ((is_array($paramValue))) {
                                        // Many to many
                                        if ($_relation instanceof Doctrine_Relation_Association) {
                                            $_refClass = $_relation->getAssociationTable()->name;
                                            $item->$_refClass->delete();
                                            $item->$_rel[1]->merge(Doctrine_Query::create()->from($_rel[1])->whereIn('id', $paramValue)->execute());
                                        }
                                    } else {
                                        if (!empty($paramValue)) {
                                            // One to many
                                            $item->$_rel[1] = Doctrine::getTable($_relation->getClass())->findOneById($paramValue);
                                        }
                                    }
                                }

                            } else if (isset($_file[1]) && !empty($paramValue['name'])) {
                                // File field
                                $_i18n = explode('i18n-', $_file[1]);

                                if (isset($_i18n[1])) {
                                    $i18nFieldName  = explode('-', $_i18n[1]);

                                    if (count($i18nFieldName) != 2) {
                                        throw new Core_Exception('Fatal error : I18n file inputs must be named file-i18n-lang-fieldname');
                                    }

                                    $path               = (isset($this->_files[$model][$i18nFieldName[1]]['path']))           ? Core_IO_Path::combine($this->_files[$model][$i18nFieldName[1]]['path'], $i18nFieldName[0])  : null;
                                    $extensions         = (isset($this->_files[$model][$i18nFieldName[1]]['extensions']))     ? $this->_files[$model][$i18nFieldName[1]]['extensions']                                      : null;
                                    $files[$_file[1]]   = Base_Classes_IO_FileUploader::prepare($i18nFieldName[1], $paramValue, $path, $extensions);

                                } else {
                                    $fieldName          = $_file[1];
                                    $path               = (isset($this->_files[$model][$fieldName]['path']))          ? $this->_files[$model][$fieldName]['path']       : null;
                                    $extensions         = (isset($this->_files[$model][$fieldName]['extensions']))    ? $this->_files[$model][$fieldName]['extensions'] : null;
                                    $files[$_file[1]]   = Base_Classes_IO_FileUploader::prepare($_file[1], $paramValue, $path, $extensions);
                                }

                            } else if (isset($_i18n[1])) {
                                // I18n field
                                $lang       = explode('-', $_i18n[1]);
                                $langArray  = explode('_', $lang[0]);
                                $langIso    = strtolower($langArray[0]) . '_' . strtoupper($langArray[1]);
                                $fieldName  = $lang[1];

                                if (substr($fieldName, 0, 4) != 'file') {
                                    $item->Translation[$langIso]->$fieldName = $paramValue;
                                }

                            } else if (isset($_datetime[1])) {
                                // Datetime field
                                $fieldName          = $_datetime[1];
                                $item->$fieldName	= null;

                                if (!empty($paramValue)) {
                                    $date				= new Zend_Date($item->$fieldName, Zend_Date::ISO_8601);
                                    $date->set($paramValue);
                                    $item->$fieldName	= $date->get(Zend_Date::ISO_8601);
                                }

                            } else if (isset($_date[1])) {
                                // Date field
                                $fieldName = $_date[1];

                                $date				= new Zend_Date($item->$fieldName, Zend_Date::ISO_8601);
                                $date->set($paramValue, Zend_Date::DATE_SHORT);
                                $item->$fieldName	= $date->get(Zend_Date::ISO_8601);

                            } else if (isset($_time[1])) {
                                // Time field
                                $fieldName  = $_time[1];

                                $date				= new Zend_Date($item->$fieldName, Zend_Date::TIME_SHORT);
                                $date->set($paramValue, Zend_Date::TIME_SHORT);
                                $item->$fieldName	= $date->get(Zend_Date::TIME_SHORT);

                           } else {
                               // Normal field
                               if ($item->contains($paramKey)) {
                                   if (isset($columns[$paramKey]) && $columns[$paramKey]['type'] == 'boolean') {
                                       $item->$paramKey = ($paramValue == '1');

                                   } elseif (empty($paramValue)) {
                                       $item->$paramKey = null;

                                   } else {
                                       $item->$paramKey = stripslashes($paramValue);
                                   }
                               }
                           }
                        }

                        foreach($manyToMany as $manyToManyClass => $manyToManyValues) {
                            if ($item->hasRelation($manyToManyClass)) {
                                $_relation = $item->getTable()->getRelation($manyToManyClass);

                                if ($_relation instanceof Doctrine_Relation_Association) {
                                    $_refClass = $_relation->getAssociationTable()->name;
                                    $item->$_refClass->delete();

                                    try {
                                        $item->$manyToManyClass->merge(Doctrine_Query::create()->from($manyToManyClass)->whereIn('id', $manyToManyValues)->execute());
                                    } catch(Doctrine_Record_Exception $e) {
                                        foreach($manyToManyValues as $value) {
                                            $_refObject             = new $_refClass();
                                            $_local                 = $_relation->getLocalFieldName();
                                            $_foreign               = $_relation->getForeignFieldName();
                                            $_refObject->$_foreign  = $value;
                                            $_refObject->$_local    = $item->id;
                                            $_refObject->save();
                                        }
                                    }
                                }
                            }
                        }

                         foreach($customs as $custom) {
                            if ($custom['valid']) {
                                try {
                                    $custom['object']->process($item, $this->_getParams());
                                } catch (Base_Classes_Customs_Exception $e) {
                                    foreach ($e->getErrors() as $fieldName => $errorCodes) {
                                        foreach ($errorCodes as $value) {
                                            $this->_namespace->errors[$fieldName][] = $value;
                                        }
                                    }
                                }
                            }
                        }

                        // Retrieves item's error stack
                        $item->isValid();

                        if (count($this->_namespace->errors)) {
                            throw new Core_Exception('Error : Item cannot be saved');
                        }

                        // Sinon on sauvegarde/insert/déplace l'élément
                        if (isset($_insertInNode)) {
                            $item->getNode()->insertAsLastChildOf($_insertInNode);
                        } else {
                            $item->save();
                        }

                        if (count($files)) {
                            foreach ($files as $fieldName => &$file) {
                                $_i18n = explode('i18n-', $fieldName);

                                if (isset($_i18n[1])) {
                                    $i18nFieldName  = explode('-', $_i18n[1]);
                                    $fieldName      = $i18nFieldName[1];
                                    $file['path']   = Core_IO_Path::combine($file['path'], $i18nFieldName[0]);
                                }

                                Base_Classes_IO_FileUploader::upload($item->id .'.'. $file['extension'], $file);

                                if (isset($this->_files[$model][$fieldName]['options']) && is_array($this->_files[$model][$fieldName]['options'])) {
                                    foreach ($this->_files[$model][$fieldName]['options'] as $optionName => $optionParams) {
                                        $optionAdapter = Base_Classes_IO_Options_Adapter::factory($optionName);
                                        $optionAdapter->process($file, $item->id .'.'. $file['extension'], $optionParams);
                                    }
                                }

                                if (isset($_i18n[1])) {
                                    $i18nFieldName                                       = explode('-', $_i18n[1]);
                                    $item->Translation[$i18nFieldName[0]]->$fieldName    = $file['extension'];
                                } else {
                                    $item->$fieldName = $file['extension'];
                                }
                            }
                        }

                        // Saves again if files have been uploaded
                        $item->save();

                        $this->_postSave($item);

                    } catch (Exception $e) {
                        // Retrieves item's errors
                        $errors = $item->getErrorStack();

                        if (count($errors) > 0) {
                            $errorList = array();

                            foreach ($errors as $fieldName => $errorCodes) {
                                foreach ($errorCodes as $value) {
                                    $this->_namespace->errors[$fieldName][] = $value;
                                }
                            }
                        } else if (!count($this->_namespace->errors)) {
                            die($e->getMessage());
                            throw new Core_Exception('Fatal error: unable to save the item');
                        }
                    }
                }
            }

            $rep = $this->_getResponse('http');
            $rep->setTemplate('json.tpl');
            $rep->data->assign('json', Zend_Json::encode(array('success' => (count($this->_namespace->errors) == 0), 'errors' => $this->_namespace->errors)));
            return $rep;
        }

        /**
         * Post save process
         *
         * @param       DbBase      $item
         * @return      void
         */
        protected function _postSave(DbBase $item)
        {}

        /**
         * Moves an element to trash
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function moveTrash()
        {
            return $this->_process(__FUNCTION__, $this->_model);
        }

        /**
         * Moves a parent to trash
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function moveTrashParent()
        {
            return $this->_process('moveTrash', $this->_parent);
        }

        /**
         * Moves a parent to trash
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function moveTrashAdjacent()
        {
            $rep            = $this->_process('moveTrash', $this->_adjacent);

            $ids            = $this->_getParam('listeId');
            $items          = new Doctrine_Collection($this->_model);

            if ($ids !== null && !empty($ids)) {
                $ids = explode('-', $ids);

                $relation  = Doctrine::getTable($this->_model)->getRelation($this->_adjacent);
                $fieldname = $relation->getLocalFieldName();

                foreach ($ids as $id) {
                    $sons = Doctrine_Query::create()
                                ->from($this->_model .' model')
                                ->leftJoin('model.'. $this->_adjacent . ' adj')
                                ->where('adj.id = ?', $id)
                                ->execute();

                    foreach ($sons as $son) {
                        $son->$fieldname = null;
                        $son->save();
                    }
                }
            }

            return $rep;
        }

        /**
         * Removes an element from trash
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function removeFromTrash()
        {
            return $this->_process(__FUNCTION__, $this->_model);
        }

        /**
         * Removes a parent from trash
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function removeFromTrashParent()
        {
            return $this->_process('removeFromTrash', $this->_parent);
        }

        /**
         * Restores an element from the trash
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function restore()
        {
            return $this->_process(__FUNCTION__, $this->_model);
        }

        /**
         * Restores an parent from the trash
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function restoreParent()
        {
            return $this->_process('restore', $this->_parent);
        }

        /**
         * Enables an element
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function enable()
        {
            return $this->_process(__FUNCTION__, $this->_model);
        }

        /**
         * Disables an element
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function disable()
        {
            return $this->_process(__FUNCTION__, $this->_model);
        }

        /**
         * Enables a parent element
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function enableAdjacent()
        {
            return $this->_process('enable', $this->_adjacent);
        }

        /**
         * Disables a parent element
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function disableAdjacent()
        {
            return $this->_process('disable', $this->_adjacent);
        }

        /**
         * Enables a parent element
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function enableParent()
        {
            return $this->_process('enable', $this->_parent);
        }

        /**
         * Disables a parent element
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function disableParent()
        {
            return $this->_process('disable', $this->_parent);
        }

        /**
         * Deletes a file
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function deleteFile()
        {
            if ($this->_request instanceof Core_Controller_Request_Json) {
                $rep = $this->_getResponse('json');

                $path = Core_IO_Path::combine(
                                            PROJECT_MEDIA_PATH,
                                            'modules',
                                            strtolower(Core_Context::get()),
                                            $this->_getParam('attributeName'),
                                            $this->_getParam('elementId') .'.'. $this->_getParam('attributeValue')
                                        );

                //Core_IO_File::delete($path);
                
                return $rep;
            }
        }

        /**
         * Sets group
         * 
         * @return      Core_Controller_Response_Abstract
         */
        public function setAdjacentParent()
        {
            $rep = $this->_getResponse('json');

            $adjacent   = $this->_adjacent;

            if ($adjacent === null) {
                return $rep;
            }

            $parent     = ($this->_intParam('parent') == 0) ? null : Doctrine_Query::create()->from($adjacent)->where('id = ?', $this->_intParam('parent'))->fetchOne();
            $ids        = $this->_getParam('ids');
            $ids        = explode('-', $ids);

            $models     = Doctrine_Query::create()
                            ->from($this->_model .' m')
                            ->whereIn('id', $ids)
                            ->execute();

            foreach ($models as $model) {
                $model->$adjacent = $parent;
                $model->save();
            }

            return $rep;
        }

        /**
         * Switch elements
         *
         * @return      Core_Controller_Response_Abstract
         */
        public function switchElements()
        {
            $rep = $this->_getResponse('json');

            $target = Doctrine_Query::create()
                        ->from($this->_getParam('model') .' m')
                        ->where('m.id = ?', $this->_getParam('target'))
                        ->fetchOne();

            $ids      = explode('-', $this->_getParam('ids'));
            $elements = Doctrine_Query::create()
                        ->from($this->_getParam('model') .' m')
                        ->whereIn('id', $ids)
                        ->execute();

            //$asPrev = (!$target->getNode()->hasPrevSibling());

            foreach ($elements as $element) {
                if ($element->id == $target->id) {
                    continue;
                }

                if ($target->lft < $element->lft) {
                    $element->getNode()->moveAsPrevSiblingOf($target);
                } else {
                    $element->getNode()->moveAsNextSiblingOf($target);
                }
            }

            return $rep;
        }

        /**
         * Gets the element hierarchical above the one given
         *
         * @return      array
         */
        public function getElementAboveId()
        {
            if ($this->_request instanceof Core_Controller_Request_Json) {
                // Parameters
                $modelRoot      = $this->_getParam('modelRoot');
                $parentRoot     = $this->_getParam('parentRoot');
                
                // Returned array
                $return     = array(    'modelId'   => null,
                                        'parentId'  => null
                                    );
                

                if (!empty($modelRoot)) {
                    
                    $_modelTable    = Doctrine::getTable($this->_model);
                    $_modelTree     = $_modelTable->getTree();
                    
                    $child          = Doctrine::getTable($this->_model)->find($modelRoot);

                    // Child exists
                    if ($child) {

                        // Model is a nested set
                        if ($_modelTree) {
                            $parent = $child->getNode()->getParent();
                            if ($parent) {
                                // Parent exists
                                if (!$parent->getNode()->isRoot()) {
                                    // Parent is not a root
                                    $return['modelId']  = $parent->id;
                                }
                            }
                        }

                        // Still not found
                        if (is_null($parent)) {
                            // Model is not a nested set
                            $parent = Doctrine_Query::create()
                                        ->from($this->_parent . 'p')
                                        ->leftJoin('p.' . $this->_model . ' m')
                                        ->where('m.id', $modelRoot)
                                        ->fetchOne();

                            if ($parent) {
                                $return['parentId']  = $parent->id;
                            }
                        }
                    }
                } elseif (!empty($parentRoot) && !empty($this->_parent)) {
                    $_parentTable   = Doctrine::getTable($this->_parent);
                    $_parentTree    = $_parentTable->getTree();

                    $child          = Doctrine::getTable($this->_parent)->find($parentRoot);

                    // Child exists
                    if ($child) {

                        // Model has to be nested set to have a parent
                        if ($_parentTree) {
                            $parent = $child->getNode()->getParent();
                            if ($parent) {
                                // Parent exists
                                if (!$parent->getNode()->isRoot()) {
                                    // Parent is not a root
                                    $return['parentId']  = $parent->id;
                                }
                            }
                        }
                    }
                }

                $rep = $this->_getResponse('json');

                $rep->setResponseContent($return);

                return $rep;
            }

        }

    ////////////////////////////////////////////////////////////////////////////
    //                            Protected Methods                           //
    ////////////////////////////////////////////////////////////////////////////

        /**
         * Process an action on a element
         *
         * @return      Core_Controller_Response_Abstract
         */
        protected function _process($action, $model)
        {
            if (class_exists($model)) {
                $id             = $this->_getParam('id');
                $listString     = $this->_getParam('listeId');

                $items          = new Doctrine_Collection($model);

                if (!empty($listString)) {
                    $listArray      = explode('-', $listString);
                    $listArrayClean = array();
                    foreach ($listArray as $currentId) {
                        if ($currentId != 0) {
                            $listArrayClean[]   = $currentId;
                        }
                    }
                    $items          = $items->merge(Doctrine_Query::create()->from($model)->whereIn('id', $listArrayClean)->execute());
                }

                if (!empty($id)) {
                    $items[]    = $items->merge(Doctrine_Query::create()->from($model)->where('id = ?', $id)->execute());
                }

                foreach ($items as $item) {
                    if ($item instanceof DbBase) {
                        if (method_exists($item, $action)) {
                            $item->$action();
                        } else {
                            throw new Core_Exception('Fatal error : The method "' . $action . '" doesn\'t exist on "' . get_class($item) . '".');
                        }
                    }
                }
            }

            if ($this->_request instanceof Core_Controller_Request_Json) {
                $rep = $this->_getResponse('json');
            } else {
                $rep    = $this->_getResponse('redirect');
                $rep->setAction('index');
                $rep->params['parentRoot']  = $this->_getParam('parentRoot');
            }

            return $rep;
        }

        /**
         * Generic action to load a form
         *
         * @param       string      $method
         * @param       string      $model
         * @param       array       $bind
         * @return      Core_Controller_Response_Abstract
         */
        protected function _form($method, $model, $bind = array('*' => true))
        {
            if ($this->_request instanceof Core_Controller_Request_Json) {
                $rep = $this->_getResponse('json');
                $rep->setResponseContent($this->_prepareEditionVariables($rep, $method, $model, null, $bind));

                return $rep;
            }
        }

        /**
         * Gets the root element of a model
         * Creates if not exist
         *
         * @param   string      $modelClass
         * @param   int         $id
         * @return  Object      $rootElement
         */
        protected function _getRootElement($modelClass, $id = null)
        {
            $modelTable = Doctrine::getTable($modelClass);
            $modelTree  = $modelTable->getTree();

            if ($modelTree) {
                // Gets the root element
                if (!is_null($id)) {
                    $rootElement = Doctrine_Query::create()->from($modelClass)
                                                            ->where('id = ?', $id)
                                                            ->fetchOne();
                } else {
                    $rootElement = Doctrine_Query::create()->from($modelClass)
                                                            ->where('level = ?', 0)
                                                            ->fetchOne();
                }

                // Creation of the root element for the parent if not exists
                if (!$rootElement) {
                    $rootElement                 = new $modelClass();
                    $rootElement->status         = DbBase::ROOT;

                    $modelTable->getTree()->createRoot($rootElement);
                }
            }

            return $rootElement;
        }

        /**
         * Return elements to display in the list from queries
         *
         * @param       array $queries
         * @return      array
         */
        protected function _getElements($queries, $model = null, $parent = null)
        {
            $elements   = array('model'     => array(),
                                'parent'    => array());

            // In order to differenciate alias from real class
            $parentClass = ($parent !== null) ? Doctrine::getTable($model)->getRelation($parent)->getClass() : null;
            $parentAlias = $parent;

            // Offset
            $_offset    = (is_null($this->_intParam('start'))) ? 0 : $this->_intParam('start');
            $_limit     = $this->_intParam('limit');

            if ($parent && !is_null($queries['parent'])) {
                // Total number of parents
                $_totalParents  = $queries['parent']->count();

                // Gets the parents
                $queries['parent']->offset($_offset);
                
                if (!is_null($_limit)) {
                    $queries['parent']->limit($_limit);
                }
                $_parents               = $queries['parent']->execute();
                $elements['parent']     = $_parents;

                // Gets the model
                $_offset    = ($_offset - $_totalParents < 0) ? 0 : $_offset - $_totalParents;
                
                $queries['model']->offset($_offset);

                if (!is_null($_limit)) {
                    $queries['model']->limit(($_limit - count($_parents)));
                }

                $elements['model']      = $queries['model']->execute();

            } else {
                if ($this->_getTotalCount()) {
                    $queries['model']->offset($_offset);
                    if (!is_null($_limit)) {
                        $queries['model']->limit($_limit);
                    }
                    $elements['model']  = $queries['model']->execute();
                } else {
                    $elements['model']  = $queries['model']->execute();
                }
            }

            $returnedList[] = array('model'     => array(),
                                    'parent'    => array());

            if (!empty($parent)) {
                // Parent's information
                $_parentTable                   = Doctrine::getTable($parentClass);
                $_parentTree                    = $_parentTable->getTree();
                $_parentRelations               = $_parentTable->getRelations();

                foreach ($elements['parent'] as $element) {
                    // Database information
                    $tmpElement                 = $element->toArray();

                    // Relations information
                    foreach ($_parentRelations as $relation) {
                        $_relationAlias = $relation->getAlias();
                        try {
                            if (get_class($element->$_relationAlias) != 'Doctrine_Collection') {
                                $tmpElement[$_relationAlias]    = $element->$_relationAlias->__toString();
                            }
                        } catch (Exception $e) {
                            
                        }
                    }

                    // Additionnal information
                    $tmpElement['id']           = $this->_parent .'-'. $element->id;
                    $tmpElement['realId']       = $element->id;
                    $tmpElement['title']        = $element->__toString();
                    $tmpElement['iconCls']      = $this->_getIconClass($element);
                    $tmpElement['type']         = 'parent';
                    $tmpElement['nested']       = ($_parentTree) ? 'true' : 'false';

                    $returnedList['parent'][]    = $tmpElement;
                }
            }

            // Model's information
            $_modelTable                    = Doctrine::getTable($model);
            $_modelTree                     = $_modelTable->getTree();
            $_modelRelations                = $_modelTable->getRelations();
            
            foreach ($elements['model'] as $element) {
                // Database information
                $tmpElement                 = $element->toArray();

                // Relations information
                foreach ($_modelRelations as $relation) {
                    $_relationAlias                 = $relation->getAlias();
                    
                    try {
                        if (get_class($element->$_relationAlias) != 'Doctrine_Collection') {
                            $tmpElement[$_relationAlias]    = $element->$_relationAlias->__toString();
                        }
                    } catch (Exception $e) {
                        
                    }
                }

                // Additionnal information
                $tmpElement['id']           = $model .'-'. $element->id;
                $tmpElement['realId']       = $element->id;
                $tmpElement['title']        = $element->__toString();
                $tmpElement['type']         = 'model';

                if ($_modelTree) {
                    $tmpElement['nested']   = 'true';
                    $tmpElement['iconCls']  = empty($parent) ? 'container' : 'file';

                } else {
                    $tmpElement['nested']   = 'false';
                    $tmpElement['iconCls']  = $this->_getIconClass($element);
                }

                if ($this->_getParam('listType') == self::LIST_TYPE_ADJACENCY) {
                    $tmpElement['_is_leaf']         = $this->_getParam('anode') !== null;
                    $tmpElement['_parent']          = $this->_getParam('anode');

                    if ($this->_getParam('anode') === null) {
                        $tmpElement['type']         = 'adjacent';
                    }
                }

                $returnedList['model'][]   = $tmpElement;
            }

            if ($this->_getParam('listType') == self::LIST_TYPE_ADJACENCY) {
                if ($this->_getParam('anode') === null) {
                    $tmpElement['id']           = $model .'-'. 0;
                    $tmpElement['realId']       = 0;
                    $tmpElement['title']        = __('base~unclassed');
                    $tmpElement['type']         = 'adjacent';
                    $tmpElement['status']       = DbBase::DISABLED;
                    $tmpElement['_is_leaf']     = false;
                    $tmpElement['_parent']      = null;
                    $returnedList['model'][]    = $tmpElement;
                }

                return (isset($returnedList['model'])) ? $returnedList['model'] : array();
            }

            return $this->_mergeElements($returnedList);
        }

        /**
         * Returns icon class
         *
         * @param       DbBase      $element
         * @return      string
         */
        protected function _getIconClass(DbBase $element)
        {
            switch (get_class($element)) {
                case $this->_parent:
                    return 'container';
                case $this->_model:
                default:
                    return 'file';
            }
        }

        /**
         * Return merged elements to display in grid
         *
         * @param array $elements
         * @return array
         */
        protected function _mergeElements(array $elements)
        {
            $merged     = array();

            if (isset($elements['model']) && is_array($elements['model'])) {
                $merged = array_merge($merged, $elements['model']);
            }

            if (isset($elements['parent']) && is_array($elements['parent'])) {
                $merged = array_merge($merged, $elements['parent']);
            }

            return $merged;
        }

        /**
         * Get the total number of element
         *
         * @return      int
         */
        protected function _getTotalCount()
        {
            if (!isset($this->_cache['totalCount'])) {
                $this->_cache['totalCount'] = 0;

                $_total = array('model' => 0, 'parent' => 0);
                
                foreach ($this->_getQueries(__FUNCTION__, $this->_model, $this->_parent) as $key => $query) {
                    if (!is_null($query)) {
                        $_total[$key]   = $query->count();
                    }
                }

                $this->_cache['totalCount'] = $this->_mergeTotalCount($_total);
            }

            return $this->_cache['totalCount'];
        }

        /**
         * Return merged total count to display in grid
         *
         * @param array $total
         * @return array
         */
        protected function _mergeTotalCount(array $total)
        {
            $merged     = 0;
            $merged     += $total['model'];
            $merged     += $total['parent'];

            return $merged;
        }

        /**
         * Get the queries of elements list
         * Returns an array of Doctrine_Query
         *
         * @param       string      $action
         * @param       string      $model
         * @param       string      $parent
         * @return      array
         */
        protected function _getQueries($action, $model = null, $parent = null)
        {
            // Defines the list of parameters
            $this->_defineListParameters($action);

            // In order to differenciate alias from real class
            $parentClass = ($parent !== null) ? Doctrine::getTable($model)->getRelation($parent)->getClass() : null;
            $parentAlias = $parent;

            // Builds the base of the queries
            $listQuery              = array();
            $listQuery['model']     = $this->_buildQuery($model);
            $listQuery['parent']    = $this->_buildQuery($parentClass);

            // Model's information
            $modelRootId            = $this->_intParam('modelRoot');
            $modelTable             = Doctrine::getTable($model);
            $modelTree              = $modelTable->getTree();
            $parentTable            = null;

            $search                 = $this->_getParam('search');

            if ($parentClass !== null) {
                // Parent's information
                $parentRootId   = ($this->_intParam('parentRoot') <= 0) ? null : $this->_intParam('parentRoot');
                $parentTable    = Doctrine::getTable($parentClass);

                $parentRoot     = ($parentRootId === null) ? false : $parentTable->findOneById($parentRootId);
                $parentTree     = $parentTable->getTree();
            }

            if ($action != 'trash' && $action != 'search' && $search != 'true') {
                // Order By
                $sort   = explode('|', $this->_getParam('sort'));
                $dir    = explode('|', $this->_getParam('dir'));

                $sortParent     = (empty($sort[1])) ? $sort[0]  : $sort[1];
                $dirParent      = (empty($dir[1]))  ? $dir[0]   : $dir[1];
                $sortModel      = $sort[0];
                $dirModel       = $dir[0];

                // Model's sorting
                if (!empty($sortModel) && $modelTable->hasField($sortModel)) {
                    $orderBy    = $sortModel . ' ';
                    $orderBy   .= (!empty($dirModel)) ? $dirModel : 'ASC';
                    $listQuery['model']->addOrderBy($orderBy);
                }

                // Lists child elements of the parent in the URL
                if ($parentClass !== null) {
                    // Parent's sorting
                    if (!empty($sortParent) && $parentTable->hasField($sortParent)) {
                        $orderBy    = $sortParent . ' ';
                        $orderBy   .= (!empty($dirParent)) ? $dirParent : 'ASC';
                        $listQuery['parent']->addOrderBy($orderBy);
                    }

                    // Gets the relation field
                    $relation = $modelTable->getRelation($parentAlias);

                    if ($relation instanceof Doctrine_Relation_Association) {
                        // Many to many relation
                        $foreignFieldName  = $relation->getForeignFieldName();
                        $localFieldName    = $relation->getLocalFieldName();
                        $association       = Doctrine_Query::create()->from($relation->getAssociationTable()->name)->where($foreignFieldName.' = ?', $parentRootId)->execute();
                        $ids               = array();

                        if ($association) {
                            foreach ($association as $currentModel) {
                                $ids[] = $currentModel->$localFieldName;
                            }
                        }

                        if (!count($ids)) {
                            $ids[] = 'NULL';
                        }

                        $listQuery['model']->whereIn('id', $ids);

                    } else {
                        // One to many relation
                        $relationField = $relation->getLocalFieldName();

                        if ($parentRootId === null) {
                            $listQuery['model']->addWhere('o.' . $relationField . ' IS NULL');
                        } else {
                            $listQuery['model']->addWhere('o.' . $relationField . ' = ?', $parentRootId);
                        }
                    }

                    if ($parentTree) {
                        // Parent is a nested set
                        if ($parentRootId !== null) {
                            // On récupère le noeud du parent
                            $parentNode = $parentTable->find($parentRootId)->getNode();
                            $listQuery['parent']->addWhere('lft > ? AND rgt < ? AND level = ?', array($parentNode->getLeftValue(), $parentNode->getRightValue(), $parentNode->getLevel() + 1));

                            if ($parentTree->getAttribute('hasManyRoots')) {
                                $listQuery['parent']->addWhere($parentTree->getAttribute('rootColumnName') .' = ?', $parent->getRootValue());
                            }

                        } else {
                            // Si aucun parent n'est demandé, on affiche le niveau 0
                            $listQuery['parent']->addWhere('level = ?', 1);
                        }

                        $listQuery['parent']->orderBy('lft');

                    } else {
                        // Parent is not a nested set
                        if ($parentRootId !== null) {
                            $listQuery['parent'] = null;
                        }
                    }
                }

                // Child elements in a nested set
                if ($modelTree) {
                    $modelRoot = $modelTable->find($modelRootId);

                    if ($modelRoot !== false) {
                        $listQuery['model']->addWhere('lft > ? AND rgt < ? AND level = ?', array($modelRoot->getNode()->getLeftValue(), $modelRoot->getNode()->getRightValue(), $modelRoot->getNode()->getLevel() + 1));
                        $listQuery['parent'] = null;

                    } else {
                        $listQuery['model']->addWhere('level = ?', 1);
                    }

                    $listQuery['model']->orderBy('lft');
                }
            }

            $this->_parseFilters($listQuery, $action, $model, $parent);

            return $listQuery;
        }

        /**
         * Parse filters and adds them to current request
         *
         * @param   &[Doctrine_Query]    &$_listQuery
         * @param       string      $action
         * @param       string      $model
         * @param       string      $parent
         */
        protected function _parseFilters(&$listQuery, $action, $model = null, $parent = null)
        {
            $params         = $this->_getParams();
            $_search        = $this->_getParam('search');
            $_modelTable    = Doctrine::getTable($model);
            $_parentTable   = null;

            // In order to differenciate alias from real class
            $parentClass = ($parent !== null) ? Doctrine::getTable($model)->getRelation($parent)->getClass() : null;
            $parentAlias = $parent;

            if ($parentClass !== null) {
                $_parentTable = Doctrine::getTable($parentClass);
            }

            foreach ($params as $paramKey => $paramValue) {
                if (!empty($paramValue)) {

                    $value  = explode('__', $paramValue);
                    $key    = explode('-', $paramKey);

                    if ($key[0] == 'rel') {
                        // Relation field
                        if ($_modelTable->hasRelation($key[1])) {
                            if ($listQuery['model'] instanceof Doctrine_Query) {
                                $_relation  = $_modelTable->getRelation($key[1]);

                                if (empty($key[2])) {
                                    if ($value[1] == 0 || $value[1] == null) {
                                        $listQuery['model']->addWhere($_relation->getLocalFieldName().' IS NULL');
                                    } else {
                                        $listQuery['model']->addWhere($_relation->getLocalFieldName().' = ?', $value[1]);
                                    }
                                }
                            }
                        }
                    } else {
                        // Simple field
                        if ($_modelTable->hasField($paramKey)) {
                            if ($listQuery['model'] instanceof Doctrine_Query) {
                                if ($value[1] == 'null') {
                                    switch($value[0]) {
                                        case '=':
                                            $listQuery['model']->addWhere($paramKey .' IS NULL');
                                            break;
                                        case '!=':
                                            $listQuery['model']->addWhere($paramKey .' IS NOT NULL');
                                            break;
                                    }
                                } else {
                                    if ($_search && ($value[0] == '=')) {
                                        $value[0]   = 'LIKE';
                                        $listQuery['model']->addWhere($paramKey .' '. $value[0] .' ?', '%'.$value[1].'%');
                                    } else {
                                        $listQuery['model']->addWhere($paramKey .' '. $value[0] .' ?', $value[1]);
                                    }
                                }
                            }
                        }

                        if (!empty($this->_parent) && $_parentTable->hasField($paramKey)) {
                            if ($listQuery['parent'] instanceof Doctrine_Query) {
                                if ($_search && ($value[0] == '=')) {
                                    $value[0]   = 'LIKE';
                                    $listQuery['parent']->addWhere($paramKey .' '. $value[0] .' ?', '%'.$value[1].'%');
                                } else {
                                    $listQuery['parent']->addWhere($paramKey .' '. $value[0] .' ?', $value[1]);
                                }
                            }
                        }
                    }
                }
            }
        }

        /**
         * Defines the parameters used for the list queries
         *
         * @param       string $action
         * @return      void
         */
        protected function _defineListParameters($action)
        {
            // Definition of the parameters for the list queries
            switch ($action) {
                case 'index':
                    $this->_listParam['where']  = array('status'    =>
                                                        array('='   =>
                                                            array(DbBase::DISABLED,
                                                                DbBase::ENABLED
                                                                )
                                                            )
                                                      );
                    break;
                case 'search':
                    $this->_listParam['where']  = array('status'    =>
                                                          array('='   =>
                                                            array(DbBase::DISABLED,
                                                                DbBase::ENABLED,
                                                                DbBase::TRASH
                                                                )
                                                            ),
                                                          array('name'      =>
                                                              array('LIKE'     =>
                                                                  array($this->_getParam('keyword'))
                                                              )
                                                          )
                                              );
                    break;
                case 'trash':
                    $this->_listParam['where']  = array('status'    =>
                                                        array('='   =>
                                                            array(DbBase::TRASH
                                                                )
                                                            )
                                                      );
                    break;

                default:
                    break;
            }
        }

        /**
         * Builds the query used for the list of elements
         *
         * @param       string $model
         * @return      Doctrine_Query
         */
        protected function _buildQuery($model)
        {
            return Base_Classes_Utils_QueryBuilder::build($model, $this->_listParam);
        }

        /**
         * Sets the variables for the edition template
         *
         * @param       Core_Controller_Response_Abstract   $rep : the current response object
         * @param       string                              $action : the current action
         * @param       string                              $model
         * @param       int                                 $id
         * @param       array                               $bind
         * @throws      Core_Exception
         * @return      void
         */
        protected function _prepareEditionVariables(Core_Controller_Response_Abstract $rep, $action, $model = null, $id = null, $bind = array('*' => true))
        {
            // Current language
            $language   = $this->_getParam('language');

            // Current model
            if ($model === null) {
                $model = $this->_model;
            }

            // List of elements ID
            $idList = array();

            if ($id === null) {
                if ($this->_intParam('elementIdList') !== null) {
                    $idList = explode('-', $this->_intParam('elementIdList'));
                }
                $_elementId = $this->_intParam('elementId');
                if ($_elementId !== null) {
                    $idList[] = $this->_intParam('elementId');
                }
            } else {
                $idList[] = $id;
            }

            $safe       = array();
            $element    = new $model();

            if (count($idList) > 0) {
                $id         = $idList[0];
                $elements   = Doctrine_Query::create()->from($model)->whereIn('id', $idList)->execute();

				if (!$elements) {
					throw new Core_Exception('Fatal error : Element must exists to be edited');
                }
            }

            if (isset($elements)) {
                foreach ($elements as $_element) {
                    if (($_element instanceof $element) || (is_null($element))) {
                        $element = $_element;
                    } else {
                        throw new Core_Exception('Fatal error : Selected elements must be the same model');
                    }
                }
            }
            
            // Retrieves fields
            $_fields = Base_Classes_Utils_TableSchema::getSchemaFromRecord($element, $bind);

            foreach ($_fields as $fieldsetKey => &$fieldsetContent) {
                foreach ($fieldsetContent as $fieldname => &$field) {
                    $field['fieldname'] = $fieldname;
                    $safe               = null;

                    if ($this->_getParam($fieldname) !== null) {
                        // Value has been posted
                        $safe = ($field['type'] == 'integer') ? $this->_intParam($fieldname) : stripslashes($this->_getParam($fieldname));

                    } elseif ($fieldname == $this->_model) {
                        // The field contains the model root id
                        $safe = $this->_intParam('modelRoot');

                    } elseif ($fieldname == $this->_parent) {
                        // The field contains the parent root id
                        $safe = $this->_intParam('parentRoot');

                    } else {
                        $safe = (isset($field['value'])) ? $field['value'] : null;
                    }

                    $field['value'] = $safe;

                    if (substr($fieldname, 0, 4) == 'file') {
                        
                        if ($id !== null && $field['value'] != '' && !is_array($field['value'])) {

                            // Normal file
                            $url                = $this->_registry['config']->urlengine->basePath .'project/media/modules/'. strtolower(Core_Context::get()) .'/'. $fieldname;
                            $field['preview']   = $url . '/'. $id .'.'. $field['value'];

                        } else if ($id !== null && is_array($field['value']) && isset($field['value'][$language])) {

                            // I18n file
                            $url                = $this->_registry['config']->urlengine->basePath .'project/media/modules/'. strtolower(Core_Context::get()) .'/'. $fieldname . '/' . $language;
                            $field['preview']   = $url . '/'. $id .'.'. $field['value'][$language];

                        } else {

                            $field['preview']   = '';

                        }
                    }
                }
            }

            if ($rep instanceof Core_Controller_Response_Http) {
                $rep->data->assign('fields', $_fields);
                $rep->data->assign('id', $id);
                $rep->data->assign('action', $action);
                $rep->data->assign('model', $model);

            } else if ($rep instanceof Core_Controller_Response_Json) {
                return array('fields' => $_fields, 'model' => $model, 'action' => $action);
            }
        }
    }
